package concursos.controladores;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.ejb.EJB;
import javax.el.ELResolver;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

import org.primefaces.event.FileUploadEvent;
import org.primefaces.event.RowEditEvent;

import concursos.interfaces.ArquivoService;
import concursos.interfaces.ConcursoService;
import concursos.modelos.Arquivo;
import concursos.modelos.Concurso;
import concursos.modelos.TipoArquivo;
import concursos.modelos.Usuario;

/**
 * ManagedBean responsável por tratar as requisições relacionados à arquivos.
 * 
 * @author Felipe
 * @author Nayane
 * @author Rafael
 * 
 */
@ManagedBean
@SessionScoped
public class AdicionarArquivoMB {
	@EJB
	private ArquivoService beanArquivo;
	@EJB
	private ConcursoService beanConcurso;
	private TipoArquivo tipoArquivo = new TipoArquivo();
	private int idTipoArquivo;
	private TipoArquivo tipoSelecionado;
	private List<TipoArquivo> listaTiposArquivo = new ArrayList<TipoArquivo>();
	private Arquivo arquivoSelecionado;
	private Usuario usuario;

	private int id_usuario;

	/**
	 * Construtor padrão.
	 */
	public AdicionarArquivoMB() {
		Object user = (Usuario) FacesContext.getCurrentInstance()
				.getExternalContext().getSessionMap().get("usuario");

		this.usuario = (Usuario) user;
		this.id_usuario = usuario.getId();
	}

	/**
	 * Adiciona um arquivo e salva no banco de dados.
	 * 
	 * @param event
	 *            Evento de upload
	 * @throws IOException
	 */
	public void adicionarArquivo(FileUploadEvent event) throws IOException {
		try {
			FacesContext context = FacesContext.getCurrentInstance();
			context.getExternalContext().getFlash().setKeepMessages(true);
			ELResolver resolver = context.getApplication().getELResolver();
			ConcursoMB concursoMB = (ConcursoMB) resolver.getValue(
					context.getELContext(), null, "concursoMB");
			Concurso concurso = concursoMB.getConcursoSelecionado();
			byte[] file = event.getFile().getContents();
			Arquivo arquivo = new Arquivo();
			arquivo.setArquivo(file);
			arquivo.setNome(event.getFile().getFileName());
			arquivo.setConcurso(concurso);
			arquivo.setFormatoArquivo(event.getFile().getContentType());
			arquivo.setTipoArquivo(this.tipoSelecionado);
			this.beanArquivo.adicionarArquivo(arquivo);
			List<Arquivo> arquivos = new ArrayList<Arquivo>();
			arquivos = concurso.getArquivos();
			arquivos.add(arquivo);
			concurso.setArquivos(arquivos);
			context.addMessage(null, new FacesMessage(event.getFile()
					.getFileName(), "O arquivo foi enviado com sucesso"));
			FacesContext.getCurrentInstance().getExternalContext()
					.redirect("detalhesConcurso.xhtml");
		} catch (Exception ex) {
			FacesContext context = FacesContext.getCurrentInstance();
			context.addMessage(null, new FacesMessage(
					FacesMessage.SEVERITY_ERROR, "Erro",
					"Selecione um tipo de arquivo v�lido"));
		}

	}

	/**
	 * Remove um arquivo.
	 */
	public void removerArquivo() {
		FacesContext context = FacesContext.getCurrentInstance();
		ELResolver resolver = context.getApplication().getELResolver();
		ConcursoMB concursoMB = (ConcursoMB) resolver.getValue(
				context.getELContext(), null, "concursoMB");
		concursoMB.getConcursoSelecionado().getArquivos()
				.remove(arquivoSelecionado);
		this.beanArquivo.excluirArquivo(arquivoSelecionado);
		context.addMessage(null, new FacesMessage("Sucesso",
				"O arquivo foi removido com sucesso"));
	}

	/**
	 * Adiciona um tipo de anexo, que é um agrupamento de arquivos.
	 */
	public void adicionarTipoArquivo() {
		FacesContext context = FacesContext.getCurrentInstance();
		try {
			this.tipoArquivo.setUsuario(this.usuario);
			this.beanArquivo.adicionarTipoArquivo(tipoArquivo);
			this.listaTiposArquivo = this.beanArquivo
					.listarTipoArquivos(id_usuario);
			this.tipoArquivo = new TipoArquivo();
			context.addMessage(null, new FacesMessage("Sucesso",
					"Tipo de Arquivo Salvo com sucesso"));
		} catch (Exception e) {
			context.addMessage(null, new FacesMessage(
					FacesMessage.SEVERITY_ERROR, "Erro",
					"Tipo de Arquivo j� existe"));
		}

	}

	/**
	 * Remove tipo de anexo.
	 */
	public void removerTipoArquivo() {
		FacesContext context = FacesContext.getCurrentInstance();
		try {
			this.beanArquivo.removerTipoArquivo(tipoSelecionado);
			this.listaTiposArquivo = this.beanArquivo
					.listarTipoArquivos(this.id_usuario);
			context.addMessage(null, new FacesMessage("Sucesso",
					"Tipo de Arquivo Excluído com sucesso"));
		} catch (Exception ex) {
			context.addMessage(null, new FacesMessage(
					FacesMessage.SEVERITY_ERROR, "Erro",
					"Não é possível excluir esse Tipo de Arquivo"));
		}
	}

	/**
	 * Busca o tipo de anexo no banco de dados de acordo com o selecionado pelo
	 * usuário.
	 */
	public void buscarTipoArquivo() {
		try {
			this.tipoSelecionado = this.beanArquivo
					.buscarTipoArquivo(this.idTipoArquivo);
		} catch (Exception ex) {
			FacesContext context = FacesContext.getCurrentInstance();
			context.addMessage(null, new FacesMessage(
					FacesMessage.SEVERITY_WARN, "Aviso",
					"É necessário selecionar um tipo de arquivo válido"));
		}

	}

	/**
	 * Retorna instância do ArquivoDAO.
	 * 
	 * @return ArquivoDAO
	 */
	public ArquivoService getBeanArquivo() {
		return beanArquivo;
	}

	/**
	 * Seta objeto ArquivoDAO.
	 * 
	 * @param beanArquivo
	 *            ArquivoDAO
	 */
	public void setBeanArquivo(ArquivoService beanArquivo) {
		this.beanArquivo = beanArquivo;
	}

	/**
	 * Retorna instância Tipo de Anexo.
	 * 
	 * @return TipoArquivo
	 */
	public TipoArquivo getTipoArquivo() {
		return tipoArquivo;
	}

	/**
	 * Seta objeto Tipo Anexo.
	 * 
	 * @param tipoArquivo
	 *            Tipo de anexo
	 */
	public void setTipoArquivo(TipoArquivo tipoArquivo) {
		this.tipoArquivo = tipoArquivo;
	}

	/**
	 * Retorna lista cotendo os tipos de anexos cadastrados.
	 * 
	 * @return Lista de tipos de anexos
	 */
	public List<TipoArquivo> getListaTiposArquivo() {
		if (this.listaTiposArquivo.isEmpty())
			return this.beanArquivo.listarTipoArquivos(this.id_usuario);
		return this.listaTiposArquivo;
	}

	/**
	 * Seta lista de tipos de anexo.
	 * 
	 * @param listaTiposArquivo
	 *            Lista de tipos de anexos
	 */
	public void setListaTiposArquivo(List<TipoArquivo> listaTiposArquivo) {
		this.listaTiposArquivo = listaTiposArquivo;
	}

	/**
	 * Retona id do tipo de anexo.
	 * 
	 * @return id
	 */
	public int getIdTipoArquivo() {
		return idTipoArquivo;
	}

	/**
	 * Seta id do tipo de anexo.
	 * 
	 * @param idTipoArquivo
	 */
	public void setIdTipoArquivo(int idTipoArquivo) {
		this.idTipoArquivo = idTipoArquivo;
	}

	/**
	 * Retona o tipo de anexo selecionado pelo usuário.
	 * 
	 * @return tipo de anexo
	 */
	public TipoArquivo getTipoSelecionado() {
		return tipoSelecionado;
	}

	/**
	 * Seta instancia do tipo de anexo selecionado.
	 * 
	 * @param tipoSelecionado
	 *            tipo de anexo selecionado pelo usuario
	 */
	public void setTipoSelecionado(TipoArquivo tipoSelecionado) {
		this.tipoSelecionado = tipoSelecionado;
	}

	/**
	 * Seta objeto tipo de anexo no objeto tipoSelecionado para ficar disponível
	 * para outras operações.
	 * 
	 * @param tipo
	 *            de anexo
	 */
	public void selecionarTipoArquivo(TipoArquivo t) {
		this.tipoSelecionado = new TipoArquivo();
		this.tipoSelecionado = t;
	}

	/**
	 * Seta o objeto enviado no objeto arquivoSelecionado para ficar disponível
	 * para outras operações.
	 * 
	 * @param arquivo
	 *            Arquivo
	 */
	public void selecionarArquivo(Arquivo arquivo) {
		this.setArquivoSelecionado(new Arquivo());
		setArquivoSelecionado(arquivo);
	}

	public void updateTipoArquivo(TipoArquivo tipoArquivo) throws IOException {
		setTipoArquivo(tipoArquivo);
	}

	/**
	 * Retona objeto arquivoSelecionado.
	 * 
	 * @return arquivo selecionado
	 */
	public Arquivo getArquivoSelecionado() {
		return arquivoSelecionado;
	}

	/**
	 * Seta objeto arquivo selecionado para ficar disponível para outras
	 * operações.
	 * 
	 * @param arquivoSelecionado
	 *            Arquivo selecionado pelo usuário
	 */
	public void setArquivoSelecionado(Arquivo arquivoSelecionado) {
		this.arquivoSelecionado = arquivoSelecionado;
	}

	public void onEdit(RowEditEvent event) {
		this.beanArquivo.adicionarTipoArquivo((TipoArquivo) event.getObject());
		this.listaTiposArquivo = this.beanArquivo
				.listarTipoArquivos(id_usuario);
		FacesContext context = FacesContext.getCurrentInstance();
		context.addMessage(null, new FacesMessage("Sucesso",
				"Tipo de arquivo alterado com sucesso."));
	}

	/**
	 * Retona id do usuário logado.
	 * 
	 * @return id
	 */
	public int getId_usuario() {
		return id_usuario;
	}

	/**
	 * Seta id do usuário logado.
	 * 
	 * @param id_usuario
	 *            id
	 */
	public void setId_usuario(int id_usuario) {
		this.id_usuario = id_usuario;
	}

	/**
	 * Retona objeto usuário.
	 * 
	 * @return Usuario
	 */
	public Usuario getUsuario() {
		return usuario;
	}

	/**
	 * Seta objeto usuário.
	 * 
	 * @param usuario
	 *            Usuario
	 */
	public void setUsuario(Usuario usuario) {
		this.usuario = usuario;
	}

}
